package eu.tanov.epf.pv.types.projectpractice.ui.pages;

import static eu.tanov.epf.pv.types.projectpractice.common.constants.ProjectPracticesConstants.PROJECT_METHODS;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.epf.authoring.ui.editors.MethodElementEditor;
import org.eclipse.epf.authoring.ui.forms.CustomCategoryDescriptionPage;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.Section;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;

import eu.tanov.epf.pv.types.projectpractice.common.constants.MethodPractice;
import eu.tanov.epf.pv.types.projectpractice.common.constants.ProjectPracticesConstants;
import eu.tanov.epf.pv.types.projectpractice.ui.i18n.ProjectPracticeUIResources;
import eu.tanov.epf.pv.types.projectpractice.ui.provider.ProjectPracticeItemProvider;
import eu.tanov.epf.pv.ui.common.util.EditorHelper;
import eu.tanov.epf.pv.ui.common.util.FormHelper;

public class ProjectPracticeDescriptionPage extends CustomCategoryDescriptionPage {

	private static final String PROJECT_PRACTICE = "Project Practice";

	private static final String PROJECT_METHOD = "Project Method";

	private static final String PRACTICE_AGILITY = "Agility Level";

	public static String METHOD_SECTION = "method_section";
	public static String PRACTICE_SECTION = "practice_section";
	public static String AGILITY_LVL_SECTION = "agility_section";
	// private SectionList allSections;

	// private Map<String, List<MethodPractice>> methodToPractices;

	protected Combo ctrl_method;

	protected boolean projectMethodOn = true;

	protected boolean projectPracticeOn = true;

	protected boolean practiceAgilityOn = true;

	protected Combo ctrl_practice;

	protected Combo ctrl_agility;

	private static final String classNameForFormTitle = ProjectPracticeUIResources.projectPractice_text;

	/**
	 * because disposed is private in parent
	 */
	private boolean disposed;

	public ProjectPracticeDescriptionPage(FormEditor editor) {
		super(editor);

		EditorHelper.updateTitleImage(editor, ProjectPracticeItemProvider.getProjectPracticeImage());
	}

	@Override
	public void init(IEditorSite site, IEditorInput input) {
		super.init(site, input);

		// without variability - if on - it searches in custom categories, not
		// in ProjectPractices
		// but it is not used - so disable
		this.variabilitySectionOn = false;

		// issue #170
		this.iconSectionOn = false;
	}

	@Override
	public void dispose() {
		super.dispose();
		disposed = true;
	}

	@Override
	protected void createFormContent(IManagedForm managedForm) {
		super.createFormContent(managedForm);

		FormHelper.updateFormText(form, classNameForFormTitle, contentElement);
	}

	@Override
	protected void addListeners() {
		super.addListeners();

		// because setFormTextWithVariableInfo() is private
		FormHelper.replaceLastListener(form.getParent(), SWT.Activate, new Listener() {
			public void handleEvent(Event event) {
				if (disposed) {
					return;
				}

				refresh(!TngUtil.isLocked(methodElement));
				FormHelper.updateFormText(form, classNameForFormTitle, contentElement);

				// do refresh variability and copyright viewer
				if (variabilitySectionOn)
					base_viewer.refresh();
				if (versionSectionOn)
					copyright_viewer.refresh();
			}
		}, "org.eclipse.epf.authoring.ui.forms.DescriptionFormPage");

		if (projectMethodOn) {
			ctrl_method.addModifyListener(modelModifyListener);
			ctrl_method.addSelectionListener(new SelectionListener() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					String projMethod = ctrl_method.getText();
					String[] relevantPractices = fetchRelevantPractices(projMethod);
					// String projPractice = ctrl_practice.getText();
					ctrl_practice.setItems(relevantPractices);
					// List<String> practiceList = Arrays
					// .asList(relevantPractices);
					// if (practiceList.contains(projPractice)) {
					// ctrl_practice.select(practiceList.indexOf(projPractice));
					// }

					// XXX method section
					List<Section> sections = contentElement.getPresentation().getSections();
					Section newMethod = UmaFactory.eINSTANCE.createSection();
					newMethod.setSectionName(METHOD_SECTION);
					newMethod.setName(projMethod);
					setSection(sections, newMethod);
					// HAX
					actionMgr.doAction(IActionManager.SET, methodUnit, UmaPackage.eINSTANCE.getMethodUnit_ChangeDate(), new Date(), -1);
				}

				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
				}
			});
		}

		if (practiceAgilityOn) {
			ctrl_agility.addModifyListener(modelModifyListener);
			ctrl_agility.addSelectionListener(new SelectionListener() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					String practiceAgility = ctrl_agility.getText();
					// XXX method section
					List<Section> sections = contentElement.getPresentation().getSections();
					Section newAgility = UmaFactory.eINSTANCE.createSection();
					newAgility.setSectionName(AGILITY_LVL_SECTION);
					newAgility.setName(practiceAgility);
					setSection(sections, newAgility);
					// HAX
					actionMgr.doAction(IActionManager.SET, methodUnit, UmaPackage.eINSTANCE.getMethodUnit_ChangeDate(), new Date(), -1);
				}

				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
				}
			});
		}
		if (projectPracticeOn) {
			ctrl_practice.addModifyListener(modelModifyListener);
			ctrl_practice.addSelectionListener(new SelectionListener() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					// XXX practice section
					String projPractice = ctrl_practice.getText();
					String projMethod = ctrl_method.getText();

					String[] relevantAgility = fetchRelevantAgility(projMethod, projPractice);

					ctrl_agility.setItems(relevantAgility);

					List<Section> sections = contentElement.getPresentation().getSections();
					Section newMethod = UmaFactory.eINSTANCE.createSection();
					newMethod.setSectionName(PRACTICE_SECTION);
					newMethod.setName(projPractice);
					setSection(sections, newMethod);
					// HAX
					actionMgr.doAction(IActionManager.SET, methodUnit, UmaPackage.eINSTANCE.getMethodUnit_ChangeDate(), new Date(), -1);
				}

				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
				}
			});
		}

	}

	private String[] fetchRelevantPractices(String projMethod) {
		List<MethodPractice> practices = ProjectPracticesConstants.methodToPractices.get(projMethod);
		Vector<String> practicesNames = new Vector<String>();
		for (int i = 0; i < practices.size(); ++i) {
			practicesNames.add(practices.get(i).getName());
		}
		return practicesNames.toArray(new String[] {});
	}

	private String[] fetchRelevantAgility(String projMethod, String projPractice) {
		List<MethodPractice> practices = ProjectPracticesConstants.methodToPractices.get(projMethod);
		Vector<String> agilityLvls = new Vector<String>();
		for (int i = 0; i < practices.size(); ++i) {
			if (practices.get(i).getName().equals(projPractice)) {
				Integer maxAgilityLvl = practices.get(i).getAgilityLvl();
				agilityLvls.add(maxAgilityLvl.toString());
				break;
			}
		}
		return agilityLvls.toArray(new String[] {});
	}

	private void setSection(List<Section> sections, Section newSection) {
		for (int i = 0; i < sections.size(); ++i) {
			if (sections.get(i).getSectionName().equals(newSection.getSectionName())) {
				sections.remove(i);
				break;
			}
		}

		sections.add(newSection);
	}

	/*
	 * Copy/pasted in order to save custom title because
	 * setFormTextWithVariableInfo() is private
	 */
	@Override
	protected boolean changeElementName(String name) {
		boolean success = actionMgr.doAction(IActionManager.SET, methodElement, UmaPackage.eINSTANCE.getNamedElement_Name(), name, -1);
		if (!success) {
			return false;
		}
		if (methodElement instanceof MethodConfiguration) {
			Resource resource = methodElement.eResource();
			if (resource != null) {
				((MethodElementEditor) getEditor()).addResourceToAdjustLocation(resource);
			}
		}
		if (ContentDescriptionFactory.hasPresentation(methodElement)) {
			Resource contentResource = contentElement.getPresentation().eResource();
			if (contentResource != null) {
				((MethodElementEditor) getEditor()).addResourceToAdjustLocation(contentResource);
			}
		}
		FormHelper.updateFormText(form, classNameForFormTitle, contentElement);
		ctrl_name.setText(name);

		return true;
	}

	/*
	 * Copy/pasted in order to save custom title because
	 * setFormTextWithVariableInfo() is private
	 */
	@Override
	public void refreshName(String newName) {
		if (newName != null) {
			if ((ctrl_name != null) && !(ctrl_name.isDisposed())) {
				if (modelModifyListener != null) {
					ctrl_name.removeModifyListener(modelModifyListener);
					ctrl_name.setText(newName);
					ctrl_name.addModifyListener(modelModifyListener);
				} else {
					ctrl_name.setText(newName);
				}
				FormHelper.updateFormText(form, classNameForFormTitle, contentElement);
			}
		}
	}

	@Override
	public void loadSectionDescription() {
		this.generalSectionDescription = ProjectPracticeUIResources.projectPractice_generalInfoSection_desc;
		this.detailSectionDescription = ProjectPracticeUIResources.projectPractice_detailSection_desc;
		this.variabilitySectionDescription = ProjectPracticeUIResources.projectPractice_variabilitySection_desc;
		this.versionSectionDescription = ProjectPracticeUIResources.projectPractice_versionInfoSection_desc;
		this.iconSectionDescription = ProjectPracticeUIResources.projectPractice_IconSection_desc;
	}

	@Override
	protected void createDetailSectionContent() {
		super.createDetailSectionContent();
		String methodSelection = "";
		// XXX method section
		List<Section> sections = contentElement.getPresentation().getSections();
		if (projectMethodOn) {
			ctrl_method = createComboWithLabel(toolkit, detailComposite, PROJECT_METHOD);
			GridData data = new GridData(400, 40);
			data.horizontalSpan = 2;
			ctrl_method.setLayoutData(data);
			for (String method : PROJECT_METHODS) {
				ctrl_method.add(method);
			}

			// XXX method section
			methodSelection = getSectionName(sections, METHOD_SECTION);
			ctrl_method.setText(methodSelection);

		}
		if (projectPracticeOn) {
			ctrl_practice = createComboWithLabel(toolkit, detailComposite, PROJECT_PRACTICE);
			GridData data = new GridData(400, 40);
			data.horizontalSpan = 2;
			ctrl_practice.setLayoutData(data);
		}

		if (practiceAgilityOn) {
			ctrl_agility = createComboWithLabel(toolkit, detailComposite, PRACTICE_AGILITY);
			GridData data = new GridData(400, 40);
			data.horizontalSpan = 2;
			ctrl_agility.setLayoutData(data);
		}

		if (!methodSelection.isEmpty()) {
			String[] relevantPractices = fetchRelevantPractices(methodSelection);
			String projPractice = ctrl_practice.getText();
			ctrl_practice.setItems(relevantPractices);
			List<String> practiceList = Arrays.asList(relevantPractices);
			if (practiceList.contains(projPractice)) {
				ctrl_practice.select(practiceList.indexOf(projPractice));
			}

			// XXX practice section
			String practice = getSectionName(sections, PRACTICE_SECTION);
			ctrl_practice.setText(practice);

			if (!practice.isEmpty()) {
				String[] relevantAgility = fetchRelevantAgility(methodSelection, practice);
				ctrl_agility.setItems(relevantAgility);

				String agility = getSectionName(sections, AGILITY_LVL_SECTION);
				List<String> agilityList = Arrays.asList(relevantAgility);
				if (agilityList.contains(agility)) {
					ctrl_agility.setText(agility);
				}
			}
		}
	}

	private Section getSection(List<Section> sections, String sectionName) {
		for (int i = 0; i < sections.size(); ++i) {
			if (sections.get(i).getSectionName().equals(sectionName)) {
				return sections.get(i);
			}
		}
		return null;
	}

	private String getSectionName(List<Section> sections, String sectionName) {
		Section section = getSection(sections, sectionName);
		if (section == null) {
			return "";
		}

		return section.getName();
	}

}
